home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / INTRFC61.ARJ / LOADER.PAS < prev    next >
Pascal/Delphi Source File  |  1991-03-27  |  5KB  |  216 lines

  1. unit loader;
  2.  
  3. interface
  4.  
  5.   uses util,globals,head;
  6.  
  7. type
  8.   hash_ptr = ^hash_rec;
  9.   hash_rec = record
  10.     byte_len : word;
  11.     table    : word_array;
  12.   end;
  13.  
  14.   list_ptr = ^list_rec;
  15.   list_rec = record
  16.     offset : word;
  17.     hash : word;
  18.     next : list_ptr;
  19.   end;
  20.  
  21.   unit_ptr = ^unit_rec;
  22.   unit_rec = record
  23.     target:word;
  24.     checksum:word;
  25.     prev_unit,next_unit : word;
  26.   end;
  27.  
  28.   unit_list_ptr = ^unit_list_rec;
  29.   unit_list_rec = record
  30.     name : string;
  31.     path : string;
  32.     obj_list : list_ptr;
  33.     own_record : word;
  34.     buffer     : byte_array_ptr;
  35.     has_symbols : boolean;
  36.   end;
  37.  
  38.   obj_ptr = ^obj_rec;
  39.   obj_rec = record
  40.     next_obj: word;  { in case of a hash collision }
  41.     obj_type : byte;
  42.     name: string;
  43.   end;
  44.  
  45. var
  46.   hash_table : hash_ptr;
  47.  
  48.   unit_list : array[1..255] of unit_list_ptr;
  49.   num_known : word;
  50.  
  51.   procedure build_list(var obj_list:list_ptr;
  52.                          buffer:byte_array_ptr;
  53.                          hash_table:hash_ptr);
  54.  
  55.   procedure add_unit(var objname:string);
  56.   function  get_unit(unit_ofs:word):unit_list_ptr;
  57.   function  get_unit_by_name(var name:string):unit_list_ptr;
  58.   function  get_unit_num(var name:string):word;
  59.  
  60. implementation
  61.  
  62.   procedure build_list(var obj_list:list_ptr;
  63.                          buffer:byte_array_ptr;
  64.                          hash_table:hash_ptr);
  65.   var
  66.     i,j,t:word;
  67.     current,new_entry : list_ptr;
  68.     obj : obj_ptr;
  69.   begin
  70.     new(obj_list);
  71.     with obj_list^ do
  72.     begin
  73.       offset := $ffff;     { set up a sentinel record }
  74.       next := nil;
  75.     end;
  76.  
  77.     with hash_table^ do
  78.       for i := 0 to byte_len div 2 do
  79.         if table[i] <> 0 then
  80.         begin
  81.           t := table[i];
  82.           repeat
  83.             current := obj_list;
  84.             while t > current^.offset do
  85.               current := current^.next;
  86.             new(new_entry);
  87.             new_entry^ := current^;
  88.             current^.offset := t;
  89.             current^.hash := i;
  90.             current^.next := new_entry;
  91.              obj := add_offset(buffer,t);
  92.              { get the next object... }
  93.             t := obj^.next_obj;
  94.           until t = 0;
  95.         end;
  96.   end;
  97.  
  98.   procedure add_unit(var objname:string);
  99.   var
  100.     size,total:word;
  101.     header:^header_rec;
  102.     unit_obj:obj_ptr;
  103.     junk : pointer;
  104.  
  105.   procedure load_buffer;
  106.   begin
  107.     with unit_list[num_known]^ do
  108.     begin
  109.       path := objname+'.tpu';
  110.       read_file(path,pointer(header),0,sizeof(header^));
  111.       if header = nil then
  112.       begin
  113.         path := uses_path+path;
  114.         read_file(path,pointer(header),0,sizeof(header^));
  115.       end;
  116.       if header <> nil then
  117.       begin
  118.         if header^.file_id <> 'TPU9' then
  119.         begin
  120.           writeln('Error:  file ',path,' is not a TP 6.0 .TPU file!');
  121.           writeln('Halting.');
  122.           halt;
  123.         end;
  124.         read_file(path,pointer(buffer),0,header^.sym_size);
  125.         if buffer <> nil then
  126.           has_symbols := true;
  127.         exit;
  128.       end;
  129.       path := '';
  130.       if got_tpl then
  131.       begin
  132.         header := pointer(tpl_buffer);
  133.         total := 0;
  134.         repeat
  135.           if header^.file_id <> 'TPU9' then
  136.           begin
  137.             writeln('Error searching TURBO.TPL.  It is not a TP 6.0 library!');
  138.             writeln('Halting.');
  139.             halt;
  140.           end;
  141.           unit_obj := add_offset(header,header^.ofs_this_unit);
  142.           if unit_obj^.name = objname then
  143.           begin
  144.             buffer := pointer(header);
  145.             has_symbols := true;
  146.             exit;
  147.           end;
  148.           size := roundup(header^.sym_size,16)
  149.                  +roundup(header^.code_size,16)
  150.                  +roundup(header^.reloc_size,16)
  151.                  +roundup(header^.const_size,16)
  152.                  +roundup(header^.vmt_size,16);
  153.           total := total+size;
  154.           header := add_offset(header,size);
  155.         until (total >= tpl_size) or (size = 0);
  156.       end;
  157.       writeln('Warning:  Can''t find unit ',objname);
  158.     end;
  159.   end;
  160.  
  161.   begin
  162.     if get_unit_by_name(objname) <> nil then
  163.       exit;
  164.  
  165.     inc(num_known);
  166.     new(unit_list[num_known]);
  167.     with unit_list[num_known]^ do
  168.     begin
  169.       name := objname;
  170.       obj_list := nil;
  171.       buffer := nil;
  172.       has_symbols := false;
  173.       getmem(junk,16-ofs(heapptr^) and $F);  { make it load at a paragraph }
  174.       load_buffer;
  175.       if has_symbols then
  176.       begin
  177.         own_record := header_ptr(buffer)^.ofs_this_unit;
  178.         inc(own_record,
  179.             4+length(obj_rec(add_offset(buffer,own_record)^).name));
  180.       end;
  181.     end;
  182.   end;
  183.  
  184.   function get_unit(unit_ofs:word):unit_list_ptr;
  185.   begin
  186.     if unit_ofs > unit_list[1]^.own_record then
  187.       get_unit := unit_list[word(add_offset(buffer,unit_ofs)^)]
  188.     else
  189.       get_unit := unit_list[1];
  190.   end;
  191.  
  192.   function get_unit_by_name(var name:string):unit_list_ptr;
  193.   var
  194.     i : word;
  195.   begin
  196.     i := get_unit_num(name);
  197.     if i <> 0 then
  198.       get_unit_by_name := unit_list[i]
  199.     else
  200.       get_unit_by_name := nil;
  201.   end;
  202.  
  203.   function get_unit_num(var name:string):word;
  204.   var
  205.     i : word;
  206.   begin
  207.     for i:=1 to num_known do
  208.       if unit_list[i]^.name = name then
  209.       begin
  210.         get_unit_num := i;
  211.         exit;
  212.       end;
  213.     get_unit_num := 0;
  214.   end;
  215. end.
  216.